<?php
namespace app\controller;

use app\common\backup;

use app\BaseController;
use app\model\User as UserModel;
use app\model\Goods as GoodsModel;
use app\model\Daily as DailyModel;
use app\model\Depart as DepartModel;
use app\model\Local as LocalModel;
use app\model\Suppliers as SuppliersModel;
use app\model\Category as CategoryModel;

use think\facade\Cookie;
use think\facade\Session;
use think\facade\Response;
use think\facade\Request;
use think\facade\Db;


class ApiPort extends BaseController{
    function __construct(){
        //数据备份机制
        auto_backup();
        //开启Session,在中间件
        //Session::start();
    }
    private function success($select_data){
        return json([
            'code' => 0,
            'isSuccess' => true,
            'httpCode' => 200,
            'data' => is_array($select_data) ? $select_data : $select_data -> toArray()
        ]);
    }
    private function fail($msg='未知错误',$code=9001){
        return json([
            'code' => $code,
            'isSuccess' => false,
            'msg' => $msg,
            'message' => $msg
        ]);
    }
    public function user_get_all(){
        $this -> need_login();
        $select = (new UserModel()) -> field(['id','username','is_root','create_time']) -> select();
        return $this -> success($select);
        //return json($select);
    }
    public function user_get_all_for_login(){
        $no_login_token = (function(){
            $hash = sha1(md5(time().'au3871jhd78f4jwjebndf32876e1'));
            Session::set('no_login_token',$hash);
            return $hash;
        })();
        $users = $select = (new UserModel()) -> field(['id','username','is_root']) -> select() -> toArray();
        if($no_login_token && gettype($users) === 'array'){
            return $this -> success([
                'no_login_token' => $no_login_token,
                'users' => $users,
            ]);
        }else{
            return $this -> fail('初始化数据校验失败');
        }

    }
    public function user_add(){
        $query = Request::param();
        if(!isset($query['username']) || !isset($query['is_root'])){
            return $this -> fail('数据不完整');
        }
        $this -> need_login();
        //halt('添加用户功能待开发');
        $res = (new UserModel()) -> save([
            'username' => $query['username'],
            'password' => '',
            'is_root' => $query['is_root']
        ]);
        if($res){
            return $this -> success([]);
        }else{
            return $this -> fail('用户添加失败');
        }
    }
    public function user_edit(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('请传入完整的参数');
        }
        $id = $query['id'];
        if(empty($id)){
            return $this -> fail('请不要传入空值');
        }
        $find = (new UserModel()) -> where('id',$id) -> find();
        if(!$find){
            return $this -> fail('该用户不存在，无法编辑');
        }
        $res = $find -> allowField(['username','is_root']) -> save($query);
        if($res){
            return $this -> success([]);
        }else{
            return $this -> fail('修改失败');
        }
        //halt('修改用户功能待开发');
        /**
         * 1.根据前端传值获取用户ID
         * 2.根据用户ID修改用户
         */
    }
    public function user_delete(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('请传入完整的参数');
        }
        $id = $query['id'];
        //halt(Session::get('userid'),$id);
        if(Session::get('userid') && Session::get('userid') == $id){
            return $this -> fail('正在使用的用户无法删除');
        }
        if(empty($id)){
            return $this -> fail('请不要传入空值');
        }
        $count = (new UserModel()) -> count();
        if($count <= 1){
            return $this -> fail('必须保留至少一个用户，否则系统将无法正常使用');
        }
        $find = (new UserModel()) -> where('id',$id) -> find();
        if(!$find){
            return $this -> fail('该用户不存在，无法删除');
        }
        $res = $find -> delete();
        if($res){
            return $this -> success([]);
        }else{
            return $this -> fail('数据有可能删除失败，请刷新页面查看');
        }
        //halt('删除用户功能待开发');
        /**
         * 1.根据前端传值获取用户ID
         * 2.根据用户ID删除用户
         */
    }
    public function user_change_password(){
        $this -> need_login();
        $success = false;
        $query = Request::param();
        $enc_text = str_replace(' ','+',$query['data'] ?? '');
        $validator = $query['validator'] ?? '';
        $dec_res = rsa_private_decrypt($enc_text);
        if(!$dec_res){
            return $this -> fail('无法获取客户端数据','M7021');
        }
        $values = json_decode($dec_res,true);
        if(!$values || !isset($values['rand']) || !$values['rand'] || !$validator){
            return $this -> fail('无法获取验证信息','M7011');
        }
        if($values['rand'] !== $validator){
            return $this -> fail('验证信息不通过，请确保您发送信息的完整性','M7012');
        }
        if(!isset($values['old_password']) || !isset($values['password']) || !isset($values['password2'])){
            return $this -> fail('系统传入的数据不完整，请依次输入旧密码、新密码、确认密码');
        }
        if(empty($values['old_password']) || empty($values['password']) || empty($values['password2'])){
            return $this -> fail('您输入的数据不完整，请依次输入旧密码、新密码、确认密码');
        }       //halt($query,$dec_res,'修改密码功能开发中');
        if($values['old_password'] === $values['password']){
            return $this -> fail('新旧密码不能一致');
        }
        if($values['password'] !== $values['password2']){
            return $this -> fail('两次新密码不一致，操作失败');
        }
        $user_id = Session::get('userid');
        if(!$user_id){
            return $this -> fail('无法获取用户信息，请确保您是在登录状态下进行的操作','M8008');
        }
        $find_user = (new UserModel()) -> where('id',$user_id) -> find();
        if(!$find_user){
            return $this -> fail('当前用户不存在或已被删除，操作无法继续');
        }
        if((empty($find_user -> password) && $values['old_password'] !== '123456') || (!empty($find_user -> password) && $find_user -> password !== generate_password_with_salt($values['old_password']))){
            return $this -> fail('旧密码输入错误，请重新输入正确的旧密码');
        }
        if(strlen($values['password']) < 6){
            return $this -> fail('请至少输入6位新密码');
        }
        $success = $find_user -> allowField(['password']) -> save([
            'password' => generate_password_with_salt($values['password'])
        ]);
        if($success){
            return $this -> success([]);
        }else{
            return $this -> fail('密码修改失败');
        }
        
        //halt($user_id);
        /**
         * 1.获取登录状态（登录下进行）
         * 2.核对旧密码的传值 与数据库进行对比
         * 3.修改为新密码
         */
    }
    public function user_replace_password(){
        halt('重置密码功能开发中');
        /**
         * 1.获取登录状态（未登录下进行）
         * 2.
         * 3.通过特定算法将输入的哈希值进行对比
         * 4.重置密码
         */
    }
    public function login(){
        //登录
        $login_success = false;
        $query = Request::param();
        //halt($query['a']);
        $enc_text = str_replace(' ','+', $query['data'] ?? '');
        $validator = $query['validator'] ?? '';
        //return;
        $dec_res = rsa_private_decrypt($enc_text);
        if(!$dec_res){
            return $this -> fail('无法获取客户端数据','M7021');
        }
        $values = json_decode($dec_res,true);
        if(!$values || !isset($values['rand']) || !$values['rand'] || !$validator){
            return $this -> fail('无法获取验证信息','M7011');
        }
        if(!isset($values['pushToken']) || !$values['pushToken']){
            return $this -> fail('无法获取客户端校验信息','M7012');
        }
        if($values['pushToken'] !== Session::get('no_login_token')){
            return $this -> fail('服务端与客户端校验信息不通过，请检查您是否同时打开了多个窗口','M7013');//，请确保您是在同一个浏览器内核下进行的登录操作
        }
        //halt($values,empty($values['username']),empty($values['password']));
        if(empty($values['username']) || empty($values['password'])){
            return $this -> fail('您输入的数据不完整，请依次输入用户名、密码');
        }
        //halt($query,$values);
        //比对数据库
        $find_user = (new UserModel()) -> where('id',$values['username']) -> find();
        if(!$find_user){
            return $this -> fail('用户不存在','M2001');
        }
        $find_user = $find_user -> toArray();
        if($find_user['password'] == '' && $values['password'] == '123456'){
            $login_success = true;
        }else{
            $gen_password = generate_password_with_salt($values['password']);
            if($gen_password === $find_user['password']){
                $login_success = true;
            }else{
                return $this -> fail('登录失败，密码错误','M3001');
            }
        }
        if($login_success){
            Session::set('is_login',1);
            Session::set('username',$find_user['username']);
            Session::set('userid',$values['username']);
            return $this -> success([
                'userid' => $values['username'],
                'username' => $find_user['username'],
                'all_user' => (new UserModel()) -> field(['id','username','is_root']) -> select() -> toArray()
            ]);
        }else{
            return $this -> fail('登录失败','M1001');
        }
        
    }
    public function logout(){
        Session::set('is_login',0);
        Session::set('username','');
        Session::set('userid','');
        return $this -> success([
            'result' => '已退出登录'
        ]);

    }
    private function need_login(){
        $is_login = $this -> get_is_login();
        if(!$is_login){
            $res = $this -> fail('需要登录');
            echo json_encode([
                'code' => 9420,
                'isSuccess' => false,
                'msg' => '您尚未登录，或已掉线，需要重新登录',
                'message' => '您尚未登录，或已掉线，需要重新登录'
            ]);
            die();
        }
    }
    private function get_is_login(){
        $is_login = Session::get('is_login');
        return !!$is_login;
    }
    public function get_login_state(){
        return $this -> success([
            'is_login' => $this -> get_is_login(),
            'username' => Session::get('username'),
            'userid' => Session::get('userid'),
            'all_user' => (new UserModel()) -> field(['id','username','is_root']) -> select() -> toArray(),
        ]);
    }
    public function goods_get_all(){//获取符合条件的所有数据
        $this -> need_login();
        //执行程序
        $query = Request::param();
        $params = [
            'search' => $query['search'] ?? '',//搜索
            'category' => $query['category'] ?? '',
            'order' => in_array($query['order'] ?? '',['name','create_time','update_time']) ? $query['order'] : 'name',
            'sort' => in_array($query['sort'] ?? '',['asc','desc']) ? $query['sort'] : 'asc'
        ];
        $select = new GoodsModel();
        
        if($params['search']){
            $params['search'] = trim($params['search']);
            // $select = $select -> where('name','like','%'.$query['search'].'%') -> whereOr('another_name','like','%'.$query['search'].'%');
            $select = $select -> where(function($query1) use ($params){
                $query1 -> where('name','like','%'.$params['search'].'%') -> whereOr('another_name','like','%'.$params['search'].'%');
            });
        }
        if($params['category']){
            $select = $select -> where('category',$query['category']);
        }
        
        /*
        $where_arr = [
            [],
            []
        ];
        if($params['search']){
            $params['search'] = trim($params['search']);
            if($params['search']){
                $where_arr[0][] = ['name','like','%'.$params['search'].'%'];
                $where_arr[1][] = ['another_name','like','%'.$params['search'].'%'];
            }
        }
        if($params['category']){
            $where_arr[0][] = ['category',$params['category']];
            $where_arr[1][] = ['category',$params['category']];
        }
        $select - $select -> where($where_arr[0]) -> whereOr($where_arr[1]);
        */
        $select = $select -> order($params['order'],$params['sort']) -> select();
        //$select = $select -> select();
        //return $this -> fail(Db::getLastSql());
        return $this -> success($select);
    }
    public function goods_get_one(){//获取对应ID的惟一数据
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('ID参数不存在',8001);
        }elseif(intval($query['id']) == 0){
            return $this -> fail('ID必须为数字',8002);
        }
        $params = [
            'id' => intval($query['id'])
        ];
        $find = new GoodsModel();
        $find = $find -> where('id',$params['id']) -> find();
        if($find){
            return $this ->success($find);
        }else{
            return $this -> fail('无法找到对应ID的数据',8003);
        }
    }
    public function goods_create(){//创建可批量
        $this -> need_login();
        //增加后商品数量必须为0
        $query = Request::param();
        if(!isset($query['data'])){
            return $this -> fail('无效的DATA参数',8011);
        }
        $data_arr = json_decode($query['data'],true);
        if(!is_array($data_arr)){
            return $this -> fail('传入的JSON数据不符合规范，操作中止！',8022);
        }
        $mx = [
            'name' => '',
            'category' => "1",
            'local' => "1",
            'img' => '',
            'detail' => '',
            'specs' => '',
            'unit' => '',
            'another_name' => '',
            'more_meter' => '',
            'count' => "0",
        ];
        $merge_data = [];
        foreach($data_arr as $v){
            $gm = new GoodsModel();
            $merge = array_merge($mx,$v,['count' => '0']);
            $res = $gm -> allowField(['name','category','local','img','detail','specs','unit','another_name','more_meter','count']) -> save($merge);
            if($res){
                $temp_find = $gm -> where($merge) -> order('id','desc') -> find();
                if($temp_find){
                    $merge['id'] = $temp_find -> id;
                }
                $merge_data[] = $merge;
            }
        }
        return $this -> success($merge_data);
    }
    public function goods_delete(){//删除单个
        $this -> need_login();
        //删除必须为0时才可以
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('ID参数不存在',8001);
        }elseif(intval($query['id']) == 0){
            return $this -> fail('ID必须为数字',8002);
        }
        $params = [
            'id' => intval($query['id'])
        ];
        $find = new GoodsModel();
        $find = $find -> where('id',$params['id']) -> find();
        if($find){
            //库存数量是否为0时才可以删除
            if($find -> count != 0){
                return $this -> fail('只有库存为0时才可以删除，请先出库或报损溢');
            }else{
                $res = $find -> delete();
                if($res){
                    return $this -> success($find);
                }else{
                    return $this -> fail('删除失败',8004);
                }
            }
        }else{
            return $this -> fail('无法找到对应ID的数据',8003);
        }
    }
    public function goods_edit(){//修改单个
        $this -> need_login();
        //修改时不可修改数量
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('ID参数不存在',8001);
        }elseif(intval($query['id']) == 0){
            return $this -> fail('ID必须为数字',8002);
        }
        $params = [
            'id' => intval($query['id'])
        ];
        $find = new GoodsModel();
        $find = $find -> where('id',$params['id']) -> find();
        if($find){
            $param = [
                'name' => $query['name'] ?? $find -> name,
                'category' => isset($query['category']) ? intval($query['category']) ? $query['category'] : $find -> category : $find -> category ,
                'local' => isset($query['local']) ? intval($query['local']) ? $query['local'] : $find -> local : $find -> local ,
                'img' => $query['img'] ?? $find -> img,
                'detail' => $query['detail'] ?? $find -> detail,
                'specs' => $query['specs'] ?? $find -> specs,
                'unit' => $query['unit'] ?? $find -> unit,
                'another_name' => $query['another_name'] ?? $find -> another_name,
                'more_meter' => $query['more_meter'] ?? $find -> more_meter
            ];
            $res = $find -> save($param);
            return $this -> success($find);
        }else{
            return $this -> fail('无法找到对应ID的数据',8003);
        }
    }
    public function goods_easy_get(){
        $this -> need_login();
        $goods_model = new GoodsModel();
        $val = $goods_model -> column(['name','unit','specs','count'],'id');
        return $this -> success($val);
    }
    public function storage(){
        $this -> need_login();
        //出入库
        $query = Request::param();
        if(!isset($query['data'])){
            return $this -> fail('无效的DATA参数',8011);
        }
        $data_arr = json_decode($query['data'],true);
        if(!is_array($data_arr)){
            return $this -> fail('传入的JSON数据不符合规范，操作中止！',8022);
        }
        $doc_id = date('YmdHis').rand(100000,999999);
        $default = [
            'time' => date('Y-m-d G:i:s'),
            'method' => '10',//10进货出货 20员工领取 30损溢
            'ua' => $_SERVER['HTTP_USER_AGENT'],
            'ip' => Request::ip(),
            'user_id' => Session::get('userid') ?? '',
            'goods_id' => '',
            'before_count' => '',
            'change_count' => '',
            'after_count' => '',
            'depart' => '',//部门
            'requ' => '',//申请人
            'empl' => '',//领用人
            'reason' => '',//事由（盘点原因）
            'remark' => '',//备注
            'doc_id' => $doc_id
        ];
        //前期检查工作
        foreach($data_arr as $v){
            if(!isset($v['goods_id'])){
                return $this -> fail('此数据下不存在商品的ID信息，操作终止！参考:'.json_encode($v),2201);
            }
            if(intval($v['goods_id']) == 0){
                return $this -> fail('此数据所链接的ID信息有误，操作终止！参考:'.json_encode($v),2202);
            }
            $find = GoodsModel::find($v['goods_id']);
            if(!$find){
                return $this -> fail('无法在库存中找到此数据，操作终止！参考:'.json_encode($v),2203);
            }elseif($find -> count + $v['change_count'] < 0 ){
                return $this -> fail('系统检测到此商品在领取或报损后库存为负数，操作终止！参考:'.json_encode($v),2204);
            }
        }
        $res_data = [];
        //数据库写入操作
        foreach($data_arr as $v1){
            $res1 = false;
            $res2 = false;
            $daily_model = new DailyModel();
            $goods_model = new GoodsModel();
            $merge_data = array_merge($default,$v1);
            $goods_find = $goods_model -> find($merge_data['goods_id']);
            $before_count = $goods_find -> count;
            $res1 = $daily_model -> allowField(['time','method','ua','ip','goods_id','before_count','change_count','after_count','depart','requ','empl','reason','remark','doc_id','user_id']) -> save(array_merge($merge_data,[
                'before_count' => $before_count,
                'after_count' => $before_count + $merge_data['change_count']
            ]));//保存记录
            if($res1){
                $res2 = $goods_find -> allowField(['count']) -> save(['count' => $goods_find -> count + $merge_data['change_count']]);//保存数量
            }else{
                return $this -> fail('无法记录变动信息');
            }
            if($res2 && $res1){
                $res_data[] = $merge_data;
            }else{
                return $this -> fail('变动信息与保存数据不符，系统出现严重错误，请联系王阳重新开发！');
            }
        }
        return $this -> success($res_data);
    }
    private function change_daily($is_in){
        $daily_model = new DailyModel();
        $query = Request::param();
        $res = $daily_model -> order('time','desc');
        if(isset($query['method']) && $query['method'] !== "0"){
            $res = $res -> where('method',$query['method']);
        }
        if(isset($query['month']) && $query['month']){
            $ar = explode('-',$query['month']);
            if(count($ar) === 2){
                $year = intval($ar[0]);
                $month = intval($ar[1]);
                if($year >= 1970 && $year < 2038 && $month >=1 && $month <= 12){
                    if($month === 12){
                        $nextyear = $year + 1;
                        $nextmonth = 1;
                    }else{
                        $nextyear = $year;
                        $nextmonth = $month + 1;
                    }
                }
                $res = $res -> where('time','>=',$year.'-'.$month.'-1 00:00:00') -> where('time','<',$nextyear.'-'.$nextmonth.'-1 00:00:00');
            }
        }
        $res = $res -> where('change_count',$is_in?'>':'<','0') -> select();
        if($res){
            return $this -> success($res);
        }else{
            return $this -> fail('出入库查询失败',7051);
        }
    }
    public function in_daily(){//查询入库的物品
        $this -> need_login();
        return $this -> change_daily(true);
    }
    public function out_daily(){//查询出库的物品
        $this -> need_login();
        return $this -> change_daily(false);
        // $daily_model = new DailyModel();
        // return $this -> success($daily_model -> order('time','desc') -> where('change_count','<=','0') -> select());
    }
    public function storage_get_doc(){//查询所有的单号
        $this -> need_login();
        $query = Request::param();
        $select = (new DailyModel()) -> order('time','desc') -> field(['doc_id','user_id','method','time','change_count','depart','requ','empl']);
        if(isset($query['noInventory']) && $query['noInventory'] == '1'){
            $select = $select -> where('method','<>','30');
        }
        if(isset($query['month']) && $query['month']){
            $ar = explode('-',$query['month']);
            if(count($ar) === 2){
                $year = intval($ar[0]);
                $month = intval($ar[1]);
                if($year >= 1970 && $year < 2038 && $month >=1 && $month <= 12){
                    if($month === 12){
                        $nextyear = $year + 1;
                        $nextmonth = 1;
                    }else{
                        $nextyear = $year;
                        $nextmonth = $month + 1;
                    }
                }
                $select = $select -> where('time','>=',$year.'-'.$month.'-1 00:00:00') -> where('time','<',$nextyear.'-'.$nextmonth.'-1 00:00:00');
            }
        }
        $select = $select -> select() -> toArray();
        $doc_arr = [];
        $res = [];
        foreach($select as $v){
            if(!in_array($v['doc_id'],$doc_arr)){
                $doc_arr[] = $v['doc_id'];
                $res[] = [
                    'doc_id' => $v['doc_id'],
                    'user_id' => $v['user_id'],
                    'time' => $v['time'],
                    'method' => $v['method'],
                    'isIn' => $v['change_count'] > 0,
                    'depart' => $v['depart'],
                    'requ' => $v['requ'],
                    'empl' => $v['empl'],
                    'count' => (function($v){
                        return (new DailyModel()) -> where('doc_id',$v['doc_id']) -> count();
                    })($v)
                ];
            }
        }
        return $this -> success($res);
        
    }
    public function storage_get_data_by_doc(){//根据单号查询出入库详情
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['doc_id'])){
            return $this -> fail('ID参数不存在',8001);
        }elseif(intval($query['doc_id']) == 0){
            return $this -> fail('ID必须为数字',8002);
        }
        $select = (new DailyModel()) -> where('doc_id',$query['doc_id']) -> order('id','asc') -> select();
        return $this -> success($select);
        //halt($query);
    }
    public function daily_get_by_goods_id(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('ID参数不存在',8001);
        }elseif(intval($query['id']) == 0){
            return $this -> fail('ID必须为数字',8002);
        }
        $params = [
            'goods_id' => intval($query['id'])
        ];
        $select = (new DailyModel()) -> where('goods_id',$params['goods_id']) -> order('time','desc') -> select();
        return $this->success($select);
    }
    public function storage_edit(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('惟一标识符不存在',8001);
        }
        if(!isset($query['doc_id'])){
            return $this -> fail('单号识符不存在',8001);
        }
        if(!isset($query['edit_basis'])){
            return $this -> fail('修改依据不存在',8306);
        }elseif(!in_array(intval($query['edit_basis']),[1,2])){
            return $this -> fail('系统无法判定修改依据',8307);
        }
        $by_id_find = (new DailyModel()) -> where('id',$query['id']) -> find();
        //检查id和单号是否匹配
        if(!$by_id_find){
            return $this -> fail('该条出入库数据不存在，操作无效',8401);
        }
        $by_id_find_arr = $by_id_find -> toArray();
        if($by_id_find_arr['doc_id'] !== $query['doc_id']){
            return $this -> fail('惟一标识符和单号不匹配，操作无法进行');
        }
        if($query['edit_basis'] == 1){
            //根据单条数据进行修改
            if(isset($query['reason']) && !$query['reason']){
                unset($query['reason']);
            }
            $res = $by_id_find -> allowField(['requ','empl','remark','reason']) -> save($query);
            if($res){
                return $this -> success(['message' => '修改成功']);
            }else{
                return $this -> fail('您的修改可能不成功，请留意页面变化',8743);
            }
        }elseif($query['edit_basis'] == 2){
            //根据整个单据进行修改
            $by_id_find_arr = $by_id_find -> toArray();
            $doc_id = $by_id_find_arr['doc_id'];
            $doc_select = (new DailyModel()) -> where('doc_id',$doc_id) -> select();
            $doc_select_arr = $doc_select -> toArray();
            if(count($doc_select_arr) == 0){
                return $this -> fail('找不到单据号('.$doc_id.')对应的内容',8761);
            }
            //$res = $doc_select -> allowField(['method','time','depart','requ','empl']) -> save($query);
            foreach($doc_select_arr as $val_data){
                $res = (new DailyModel()) -> where('id',$val_data['id']) -> find() -> allowField(['method','time','depart','requ','empl']) -> save($query);
            }
            if($res){
                return $this -> success(['message' => '修改成功']);
            }else{
                return $this -> fail('您的修改可能不成功，请留意页面变化',8744);
            }
        }else{
            return $this -> fail('系统无法判定修改依据，操作无法进行');
        }

    }
    public function storage_delete(){
        $this -> need_login();
        //撤销必须保证的条件
        /**
         * 1.只有刚刚发生的单子才能撤销
         * 2.只有24小时以内的单子才能撤销
         * 3.只有当数量和当前数量匹配时才能撤销
         * 4.若撤销的商品中有已删除的则不能撤销
         * 5.数量反向运算后与此单之前的数量不匹配时不可撤销
         * 
         * 撤销后保证的几点
         * 1.原单据删除前标注已撤销
         * 2.数量恢复到此单录入前的
         */
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('惟一标识符不存在',8001);
        }
        if(!isset($query['doc_id'])){
            return $this -> fail('单号识符不存在',8001);
        }
        if(!isset($query['delete_basis'])){
            return $this -> fail('删除依据不存在',8306);
        }elseif(!in_array(intval($query['delete_basis']),[1,2])){
            return $this -> fail('系统无法判定删除依据',8307);
        }
        $last_doc_id_find = (new DailyModel()) -> order('create_time','desc') -> find();
        if(!$last_doc_id_find){
            return $this -> fail('无法获取最后一次的单据，操作无法进行！');
        }
        $last_doc_id_find_arr = $last_doc_id_find -> toArray();
        if(!isset($last_doc_id_find_arr['doc_id'])){
            return $this -> fail('最后一次的单据不完整',8481);
        }
        $last_doc_id = $last_doc_id_find_arr['doc_id'];//最后一次单号
        if($last_doc_id !== $query['doc_id']){
            return $this -> fail('只有最近的一个单据(或单据下的数据)可以撤销，此单据(或单据下的数据)不满足此条件，您可通过新增出入库单进行反向操作');
        }
        //寻找目标数据,校验前端传入的id和doc_id是否一一对应
        $for_id_find = (new DailyModel()) -> where('id',$query['id']) -> find();
        if(!$for_id_find){
            return $this -> fail('此ID下的目标数据不存在',8471);
        }
        $for_id_find_arr = $for_id_find -> toArray();
        if(!isset($for_id_find_arr['doc_id'])){
            return $this -> fail('此ID下的目标数据字段不完整',8742);
        }
        if($for_id_find_arr['doc_id'] !== $query['doc_id']){
            return $this -> fail('此ID下的目标数据中的单号数据与传值单号数据不匹配,请勿通过篡改数据的方式攻击');
        }
        if(time() - strtotime($for_id_find_arr['create_time']) > (60*60*24)){
            return $this -> fail('超过24小时的出入库数据不能撤销');
        }
        //halt($last_doc_id);
        //查找符合预期的所有数据
        $target_select = (new DailyModel()) -> where('doc_id',$query['doc_id']);
        if(intval($query['delete_basis']) !== 2){
            $target_select = $target_select -> where('id',$query['id']);
        }
        $target_select = $target_select -> select();
        $target_select_arr = $target_select -> toArray();
        if(count($target_select_arr) === 0){
            return $this -> fail('无法撤销，因为没有检索到任何出入库数据');
        }
        if(count($target_select_arr) > 10){
            return $this -> fail('此单据的项目过多，请逐条撤销，将撤销依据改为“撤销该条数据”后重试');
        }
        // 遍历。检查每条数据中的与商品本身具有的属性是否一致
        foreach($target_select_arr as $v){
            //检查自身的数量变化是否有问题
            if($v['change_count'] == 0){
                return $this -> fail('此单据下惟一标识码为'.$query['id'].'的数据数量变化为零，无法撤销！');
            }
            if($v['before_count'] + $v['change_count'] !== $v['after_count']){
                return $this -> fail('此单据下惟一标识码为'.$query['id'].'的数据存在计算出问题的数量变化，无法撤销！');
            }
            //$v['after_count'];//必须和数据当前的一致
            $goodsinfo_find = (new GoodsModel()) -> where('id',$v['goods_id']) -> find();
            if(!$goodsinfo_find){
                return $this -> fail('此单据中惟一标识码为'.$query['id'].'的数据含有已删除或不存在的物品，无法撤销！');
            }
            $goodsinfo_find_arr = $goodsinfo_find -> toArray();
            if($goodsinfo_find_arr['count'] !== $v['after_count']){
                return $this -> fail('此单据下惟一标识码为'.$query['id'].'的结余数据与物品的实际数据不符，无法撤销！');
            }
        }
        $res_data = [];
        foreach($target_select_arr as $v){
            //将本条数据删除
            $find = (new DailyModel()) -> where('id',$v['id']) -> find();
            $find_arr = $find -> toArray();
            $before_count = $find_arr['before_count'];
            $change_count = $find_arr['change_count'];
            $after_count = $find_arr['after_count'];
            $goods_id = $find_arr['goods_id'];
            $goods_find = (new GoodsModel()) -> where('id',$goods_id) -> find();
            $goods_find_arr = $goods_find -> toArray();
            $goods_name = $goods_find_arr['name'];
            $find -> allowField(['remark']) -> save([
                'remark' => '【已撤销数据】'. $find_arr['remark']
            ]);
            $find_for_del = (new DailyModel()) -> where('id',$v['id']) -> find();
            $find_for_del -> delete();
            $goods_find -> allowField(['count']) -> save([
                'count' => $before_count
            ]);
            $res_data[] = '物品【'.$goods_name.'】原数量['.$before_count.']'.($change_count < 0 ? '-' : '+').'['.abs($change_count).']=['.$after_count.']，现数量为'.$before_count.'';
        }
        return $this -> success(['message_data' => $res_data]);
    }
    public function category_get(){
        $this -> need_login();
        return $this -> success((new CategoryModel()) -> select());
    }
    public function category_edit(){
        $this -> need_login();
        $query = Request::param();
        $category_model = new CategoryModel();
        if(!isset($query['name'])){
            return $this -> fail('缺少必要的参数，程序中止',7043);
        }
        if(isset($query['id'])){
            $find = $category_model -> find($query['id']);
            if(!$find){
                return $this -> fail('当前惟一标识符下无数据',7041);
            }
            $res = $find -> allowField(['id','name']) -> save($query);
        }else{
            $res = $category_model -> allowField(['id','name']) -> save($query);
        }
        if($res){
            return $this -> success(isset($find) ? $find : ['res'=>$res]);
        }else{
            return $this -> fail('当前操作可能失败，请刷新页面后重新检查',7042);
        }
    }
    public function category_delete(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('缺少惟一标识符，操作无法进行',7031);
        }
        $find = (new CategoryModel()) -> find($query['id']);
        if(!$find){
            return $this -> fail('未找到要删除的数据',7032);
        }
        $res = $find -> delete();
        if($res){
            return $this -> success($find);
        }else{
            return $this -> fail('删除失败',7033);
        }
    }
    public function local_get(){
        $this -> need_login();
        return $this -> success((new LocalModel()) -> select());
    }
    public function local_edit(){
        $this -> need_login();
        $query = Request::param();
        $local_model = new LocalModel();
        if(!isset($query['name'])){
            return $this -> fail('缺少必要的参数，程序中止',7043);
        }
        if(isset($query['id'])){
            $find = $local_model -> find($query['id']);
            if(!$find){
                return $this -> fail('当前惟一标识符下无数据',7041);
            }
            $res = $find -> allowField(['id','name']) -> save($query);
        }else{
            $res = $local_model -> allowField(['id','name']) -> save($query);
        }
        if($res){
            return $this -> success(isset($find) ? $find : ['res'=>$res]);
        }else{
            return $this -> fail('当前操作可能失败，请刷新页面后重新检查',7042);
        }
    }
    public function local_delete(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('缺少惟一标识符，操作无法进行',7031);
        }
        $find = (new LocalModel()) -> find($query['id']);
        if(!$find){
            return $this -> fail('未找到要删除的数据',7032);
        }
        $res = $find -> delete();
        if($res){
            return $this -> success($find);
        }else{
            return $this -> fail('删除失败',7033);
        }
    }
    public function depart_get(){
        $this -> need_login();
        return $this -> success((new DepartModel()) -> select());
    }
    public function depart_edit(){
        $this -> need_login();
        $query = Request::param();
        $depart_model = new DepartModel();
        if(!isset($query['name'])){
            return $this -> fail('缺少必要的参数，程序中止',7043);
        }
        if(isset($query['id'])){
            $find = $depart_model -> find($query['id']);
            if(!$find){
                return $this -> fail('当前惟一标识符下无数据',7041);
            }
            $res = $find -> allowField(['id','name','local','includes']) -> save($query);
        }else{
            $res = $depart_model -> allowField(['id','name','local','includes']) -> save($query);
        }
        if($res){
            return $this -> success(isset($find) ? $find : ['res'=>$res]);
        }else{
            return $this -> fail('当前操作可能失败，请刷新页面后重新检查',7042);
        }
    }
    public function depart_delete(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('缺少惟一标识符，操作无法进行',7031);
        }
        $find = (new DepartModel()) -> find($query['id']);
        if(!$find){
            return $this -> fail('未找到要删除的数据',7032);
        }
        $res = $find -> delete();
        if($res){
            return $this -> success($find);
        }else{
            return $this -> fail('删除失败',7033);
        }
    }
    public function suppliers_get(){
        $this -> need_login();
        return $this -> success((new SuppliersModel()) -> select());
    }
    public function suppliers_edit(){
        $this -> need_login();
        $query = Request::param();
        $suppliers_model = new SuppliersModel();
        if(!isset($query['name'])){
            return $this -> fail('缺少必要的参数，程序中止',7043);
        }
        if(isset($query['id'])){
            $find = $suppliers_model -> find($query['id']);
            if(!$find){
                return $this -> fail('当前惟一标识符下无数据',7041);
            }
            $res = $find -> allowField(['id','name','includes','telephone']) -> save($query);
        }else{
            $res = $suppliers_model -> allowField(['id','name','includes','telephone']) -> save($query);
        }
        if($res){
            return $this -> success(isset($find) ? $find : ['res'=>$res]);
        }else{
            return $this -> fail('当前操作可能失败，请刷新页面后重新检查',7042);
        }
    }
    public function suppliers_delete(){
        $this -> need_login();
        $query = Request::param();
        if(!isset($query['id'])){
            return $this -> fail('缺少惟一标识符，操作无法进行',7031);
        }
        $find = (new SuppliersModel()) -> find($query['id']);
        if(!$find){
            return $this -> fail('未找到要删除的数据',7032);
        }
        $res = $find -> delete();
        if($res){
            return $this -> success($find);
        }else{
            return $this -> fail('删除失败',7033);
        }
    }
    public function generate_all(){
        $this -> need_login();
        $generate = [];
        $all_table = ['category','daily','depart','goods','local','suppliers','user'];
        foreach($all_table as $v){
            $generate[$v] = Db::name($v) -> order('create_time','asc') -> select();
        }
        return $this -> success($generate);

    }
    public function generate_con(){
        sleep(1);
        $query = Request::param();
        foreach(['category','month','range','field','sort','paper_orientation'] as $v){
            if(!isset($query[$v]) || empty($query[$v])){
                return $this -> fail('传入的参数不完整');
            }
        }
        $temp_month = explode('-',$query['month']);
        if(!isset($temp_month[1])){
            return $this -> fail('月份的格式不正确');
        }
        $year = $temp_month[0];
        $month = $temp_month[1];
        
        $next_year = $year;
        $next_month = $month + 1;

        if($next_month > 12){
            $next_month = $next_month - 12;
            $next_year = $next_year + 1;
        }

        $is_in = true;
        $range = $query['range'];
        if($range % 10 !== 0){
            $is_in = false;
            $range = $range - 1;
        }

        //return $this -> fail(ceil($query['sort']/2));
        $select = (new DailyModel()) 
            -> where('method',''.$range) 
            -> where('time','>=',$year.'-'.$month.'-1 00:00:00') 
            -> where('time','<',$next_year.'-'.$next_month.'-1 00:00:00') 
            -> where('change_count',$is_in ? '>' : '<' ,0) 
            -> order( ['time','time','depart'][ceil($query['sort']/2)] ?? 'time' ,$query['sort']%2 ? 'ASC' : 'DESC');
        if($query['category'] > 0){
            $goods_select = (new GoodsModel()) -> where('category',''.$query['category']) -> column('id');
            // halt($goods_select);
            $select = $select -> where('goods_id','in',$goods_select);
        }
        $select = $select -> select();
        return $this -> success($select);
    }
}